package com.newflypig.jblog.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;


import com.geetest.sdk.java.GeetestLib;
import com.newflypig.jblog.model.Article;
import com.newflypig.jblog.model.ArticleDateMap;
import com.newflypig.jblog.model.BlogConfig;
import com.newflypig.jblog.model.Pager;
import com.newflypig.jblog.model.Result;
import com.newflypig.jblog.model.Weight;
import com.newflypig.jblog.service.IArticleService;
import com.newflypig.jblog.service.IBlogService;
import com.newflypig.jblog.service.IWeightService;
import com.newflypig.jblog.util.FreemarkerUtil;


import freemarker.template.TemplateException;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@Controller
public class BaseController {
	@Autowired
	private IArticleService articleService;
	
	@Autowired
	private IBlogService blogService;
	
	@Autowired
	private IWeightService weightService;

	@RequestMapping({"/index.html","/index.jsp","/index.php"})
	public String welcom(){
		return "redirect:/";
	}
	
	@RequestMapping("/")
	public ModelAndView index(){
		/**
		 * TODO 对于archives和menuList做长期缓存，每隔1小时缓存一次（后台提供手工强制更新），不需要每次访问首页时都进行查询
		 */
		Pager<Article> pagerArticles = this.articleService.findPagerByMenu(1, BlogConfig.MENU_INDEX_URL_NAME);
		List<Article>  headArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_HEAD, BlogConfig.MENU_INDEX_URL_NAME);
		List<Article>  footArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_FOOT, BlogConfig.MENU_INDEX_URL_NAME);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("headArticles", headArticles);
		mv.addObject("footArticles", footArticles);
		return mv;
	}
	
	/**
	 * 「日志列表」页面
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws TemplateException
	 * TODO：该页面请求比较费时，首先检索整个数据库，然后再用算法进行分组，以后应将此页面静态化处理。
	 */
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView list(HttpServletRequest request) throws IOException, TemplateException{
		List<Article> articleList = this.articleService.findAllForList();
		String templateFilePath = request.getServletContext().getRealPath("/WEB-INF/views/ftl");
		ModelAndView mv = new ModelAndView("index");
		
		//对提取的日志进行年月分组
		List<ArticleDateMap> admList = new ArrayList<>();
		articleList.stream().forEach(article -> {
			int index = this.getContainsDateIndex(admList, article);
			if(index == -1){
				ArticleDateMap adm = new ArticleDateMap(new SimpleDateFormat("yyyy年MM月").format(article.getCreateDate()));
				adm.getArticleList().add(article);
				admList.add(adm);
			}else{
				ArticleDateMap adm = admList.get(index);
				adm.getArticleList().add(article);
			}
		});
		
		String html = null;
		html = new FreemarkerUtil().generateSingleAriticleListHtml(admList, templateFilePath);
		
		Article article = new Article();
		article.setHtml(html);
		List<Article> headArticles = new ArrayList<>();
		headArticles.add(article);
		
		mv.addObject("headArticles", headArticles);
		
		return mv;
	}
	
	/**
	 * 对日志进行年月分组，算法如下
	 * 如果列表中没有此日志的年月标记，则添加，
	 * 如果列表中有某个年月标记，则将此日志追加到该年月标记对应的节点中去。
	 * @param admList
	 * @param article
	 * @return
	 */
	private int getContainsDateIndex(List<ArticleDateMap> admList, Article article) {
		for(int index = 0 ; index < admList.size(); index ++){
			String date = new SimpleDateFormat("yyyy年MM月").format(article.getCreateDate());
			if(date.equals(admList.get(index).getDate()))
				return index;
		}
		return -1;
	}

	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public ModelAndView login(HttpServletRequest  request){
		ModelAndView mav = new ModelAndView("login");
		if(request.getParameter("error") != null){
			mav.addObject("errorMsg",request.getSession().getAttribute("exceptionMsg"));
		}
		return mav;
	}
	
	@RequestMapping(value="/page/{page}",method=RequestMethod.GET)
	public ModelAndView page(@PathVariable Integer page){
		Pager<Article> pagerArticles = this.articleService.findPagerByMenu(page, BlogConfig.MENU_INDEX_URL_NAME);
		List<Article>  headArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_HEAD, BlogConfig.MENU_INDEX_URL_NAME);
		List<Article>  footArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_FOOT, BlogConfig.MENU_INDEX_URL_NAME);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("headArticles", headArticles);
		mv.addObject("footArticles", footArticles);
		return mv;
	}
	
	@RequestMapping(value="/{menuUrlName}",method=RequestMethod.GET)
	public ModelAndView menu(@PathVariable String menuUrlName){
		Pager<Article> pagerArticles = this.articleService.findPagerByMenu(1, menuUrlName);
		List<Article>  headArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_HEAD, menuUrlName);
		List<Article>  footArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_FOOT, menuUrlName);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("headArticles",  headArticles);
		mv.addObject("footArticles",  footArticles);
		mv.addObject("urlName",   "/" + menuUrlName);
		return mv;
	}
	
	@RequestMapping(value="/{menuUrlName}/page/{page}",method=RequestMethod.GET)
	public ModelAndView menuPage(@PathVariable String menuUrlName, @PathVariable Integer page){
		Pager<Article> pagerArticles = this.articleService.findPagerByMenu(page, menuUrlName);
		List<Article>  headArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_HEAD, menuUrlName);
		List<Article>  footArticles  = this.articleService.findHFArticlesByMenu(Article.TYPE_ARCHIVE_FOOT, menuUrlName);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("headArticles",  headArticles);
		mv.addObject("footArticles",  footArticles);
		mv.addObject("urlName",   "/" + menuUrlName);
		return mv;
	}
	
	@RequestMapping(value="/tag/{tagUrlName}",method=RequestMethod.GET)
	public ModelAndView tag(@PathVariable String tagUrlName){
		Pager<Article> pagerArticles = this.articleService.findPagerByTag(1, tagUrlName);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("urlName",   "/tag/" + tagUrlName);
		return mv;
	}
	
	@RequestMapping(value="/tag/{tagUrlName}/page/{page}",method=RequestMethod.GET)
	public ModelAndView tagPage(@PathVariable String tagUrlName, @PathVariable Integer page){
		Pager<Article> pagerArticles = this.articleService.findPagerByTag(page, tagUrlName);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("urlName",   "/tag/" + tagUrlName);
		return mv;
	}
	
	@RequestMapping(value="/archive/{archiveUrlName}",method=RequestMethod.GET)
	public ModelAndView archive(@PathVariable String archiveUrlName){
		Pager<Article> pagerArticles = this.articleService.findPagerByArchive(1, archiveUrlName);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("urlName",   "/archive/" + archiveUrlName);
		return mv;
	}
	
	@RequestMapping(value="/archive/{archiveUrlName}/page/{page}",method=RequestMethod.GET)
	public ModelAndView archivePage(@PathVariable String archiveUrlName, @PathVariable Integer page){
		Pager<Article> pagerArticles = this.articleService.findPagerByArchive(page, archiveUrlName);
		
		ModelAndView mv = new ModelAndView("index");
		mv.addObject("pagerArticles", pagerArticles);
		mv.addObject("urlName",   "/archive/" + archiveUrlName);
		return mv;
	}
	
	@RequestMapping(value="/sitemap.xml", method=RequestMethod.GET)
	public ModelAndView sitemap(){
		ModelAndView mav = new ModelAndView("sitemap");
		mav.addObject("today", LocalDate.now().toString());
		mav.addObject("urls",  this.blogService.getBlogUrls());
		return mav;
	}
	
	/**
	 * Geetest验证码输出 
	 */
	@RequestMapping(value = "/getGeetestStep1Data", method = RequestMethod.GET)  
    public ModelAndView getGeetestStep1Data(HttpSession session) {  
        Result result = new Result();
        
        GeetestLib gtSdk = new GeetestLib(BlogConfig.GEETEST_AK, BlogConfig.GEETEST_SK);
        
        int gtServerStatus = gtSdk.preProcess();
        
        //将服务器状态设置到session中
        session.setAttribute(GeetestLib.SERVER_STATUS_SESSION_KEY, gtServerStatus);//放入session，用于后面的验证
        
        String resStr = gtSdk.getResponseStr();
        
        result.setData(resStr);
        
        return new ModelAndView("ajaxResult", "result", result);
    }
	
	/**
	 * 获取体重数据
	 * @return
	 */
	@RequestMapping(value = "/getWeightJson", method = RequestMethod.GET)
	public ModelAndView getWeightJson(){
		Result result = new Result();
		
		List<Weight> list = weightService.findAll();
		
		Gson gson = new GsonBuilder()  
				  .setDateFormat("yyyy-MM-dd HH:mm")  
				  .create();
		
		result.setData(gson.toJson(list));
		return new ModelAndView("ajaxResult", "result", result);		
	}
}
